package com.apes.scm.voucher.service.builder;

import com.apes.scm.account.account.model.InventoryConsign;
import com.apes.scm.account.account.model.InventoryMode;
import com.apes.scm.account.account.service.InventoryConsignService;
import com.apes.scm.account.method.Batch;
import com.apes.scm.account.method.BatchMethod;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.service.BusinessType;
import com.apes.scm.voucher.service.VoucherType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

import static java.lang.Math.abs;

/**
 * 功能：客户寄售消耗凭证构造器
 *
 * @author xul
 * @create 2018-10-18 9:26
 */
@Component
public class CustomerConsignVoucherBuilder extends AbstractVoucherBuilder {

    @Autowired
    InventoryConsignService icService;

    public CustomerConsignVoucherBuilder() {
        this.voucherType = VoucherType.CUSTOMER_CONSUME;
        this.BusinessTypes = new String[]{BusinessType.CUSTOMER_CONSUME_ORDER_VOUCHER, BusinessType.CUSTOMER_CONSUME_RETURN_VOUCHER};
    }

    /**
     * 功能：创建凭证
     */
    @Override
    public Voucher create(Voucher voucher) {
        if (!("Customer".equals(voucher.getPartner().getRole().getId()))) {
            throw new RuntimeException("销售凭证请指定客户角色的合作伙伴[" + voucher.getPartner().getId() + "]!");
        }

        /**保存凭证**/
        voucher = save(voucher);

        /**成本核算/价值评估**/
        costing(voucher);

        /**消耗客户寄售库存**/
        consume(voucher);

        /*设置寄售库存方式*/
        voucher.setInventoryMode(InventoryMode.IM_CONSIGN);

        /**创建客户帐单**/
        invoiced(voucher);

        return voucher;
    }

    /**
     * 消耗客户寄售库存
     */
    public void consume(Voucher voucher) {
        boolean isReturn = voucher.isReturned();
        PartyRole company = voucher.getCompany();
        PartyRole customer = voucher.getPartner();

        voucher.getVoucherItems().stream().forEach(voucherItem -> {
            new BatchMethod<Batch>() {

                @Override
                public Iterable wrap() {
                    if (voucherItem.getInventoryConsign() != null) {
                        Batch batch = new Batch();
                        batch.setEntity(voucherItem.getInventoryConsign());
                        batch.setQty(abs(voucherItem.getProductQty()));
                        List<Batch> batches = new ArrayList();
                        batches.add(batch);
                        return batches;
                    }

                    if (!isReturn) {
                        List<InventoryConsign> inventoryConsigns = icService.findInventoryConsignForOrder(company, customer, voucherItem.getProduct(), voucherItem.computeBasePrice());
                        return icService.wrapBatch(inventoryConsigns, voucherItem.getUom(), ic -> ic.getBalanceQty() - ic.getFrostBalanceQty());
                    } else {
                        List<InventoryConsign> inventoryConsigns = icService.findInventoryConsignForReturn(company, customer, voucherItem.getProduct(), voucherItem.computeBasePrice());
                        return icService.wrapBatch(inventoryConsigns, voucherItem.getUom(), ic -> ic.getConsumeQty() - ic.getFrostConsumeQty());
                    }
                }

                @Override
                public void succeed(Batch batch, double increment) {
                    InventoryConsign stock = (InventoryConsign) batch.getEntity();
                    double qty = voucherItem.getUom().computeQty(increment, stock.getUom(), true);
                    if (!isReturn) {
                        if (voucherItem.getInventoryConsign() != null) {
                            stock.changeFrostBalanceQty(-1 * qty);
                        }
                        stock.changeBalanceQty(-1 * qty);
                        stock.changeConsumeQty(qty);
                    } else {
                        if (voucherItem.getInventoryConsign() != null) {
                            stock.changeFrostConsumeQty(-1 * qty);
                        }
                        stock.changeBalanceQty(increment);
                        stock.changeConsumeQty(-1 * qty);
                    }
                    icService.save(stock);
                }

                @Override
                public void error(double surplus) {
                    throw new RuntimeException("商品：["+voucherItem.getProduct().getId()+"]" + voucherItem.getProduct().getName() + " 寄售库存数量少 " + surplus + voucherItem.getUom().getName() + "！");
                }
            }.execute(abs(voucherItem.getProductQty()));
        });
    }

}
